<template>
  <span class="upload-button-wrapper">
    <ElUpload
      ref="upload"
      class="upload-button"
      style="display: inline-block"
      :show-file-list="false"
      :headers="headers"
      :http-request="uploadFile"
      :accept="accept"
      :disabled="inputDisabled"
      :multiple="multiple"
      :action="action"
      :before-upload="beforeUploadFile"
      :data="{ unid: innerUnId, type, ...extraData }"
      v-bind="$attrs"
      auto-upload>
      <template v-if="btnStyle === 'attachment'" #trigger>
        <ElButton size="small" type="text" icon="fa fa-paperclip icon-attachment" />
      </template>
      <template v-else-if="btnStyle === 'button'" #trigger>
        <slot v-if="btnStyle === 'button'" name="button">
          <ElButton size="mini" type="primary" icon="fa fa-plus">添加文件</ElButton>
        </slot>
      </template>
      <span
        v-if="btnStyle === 'attachment'"
        style="margin-left: 4px; font-weight: normal"
        @click.prevent="showDialog = true"
        >(<span style="color: #2d8cf0; text-decoration: underline; cursor: pointer">{{ fileList.length }}</span
        >)</span
      >
    </ElUpload>
    <ElementDialog
      v-if="btnStyle === 'attachment'"
      v-dialog-drag
      :close-on-click-modal="false"
      custom-class="el-dialog-border"
      :modal="false"
      title="附件列表"
      :visible.sync="showDialog"
      append-to-body
      center
      width="400px">
      <div class="upload-button-file-list">
        <template v-if="fileList.length">
          <div v-for="file in fileList" :key="file.id" class="file-uploader-file-item">
            <i :style="{ backgroundImage: `url(${getFileIcon(file.fileType)})` }" class="file-icon"></i>
            <span class="flex-item ellipsis-1" style="overflow: hidden">{{ file.fileName }}</span
            ><span>（{{ file.fileSize | formatSize }}）</span>
            <span v-if="!disabled" class="handle-buttons">
              <ElButton class="el-button--danger" type="text" @click="removeFile(file)">删除</ElButton></span
            >
          </div>
        </template>
        <template v-else>
          <div class="file-list-empty">暂无附件！</div>
        </template>
      </div>
    </ElementDialog>
  </span>
</template>

<script>
  import { findAllByParentUnid, getUploadUrl, getHeader, remove } from '@/api/attachment/attachment'
  import { getFileSuffix } from '@web-utils/core'
  import { getFileIcon } from '@/util'
  import { ACCEPT_CONFIG } from '@/components/uploader/js/config'
  import { uploadFile } from '@/api/file'

  export default {
    name: 'UploadButton',
    inject: {
      elForm: {
        default: ''
      },
      elFormItem: {
        default: ''
      }
    },
    props: {
      unid: String,
      limitSize: {
        type: Number,
        default: ACCEPT_CONFIG.getLimitSize()
      },
      disabled: Boolean,
      multiple: {
        type: Boolean,
        default: false
      },
      accept: {
        type: String,
        default: '*/*'
      },
      btnStyle: {
        type: String,
        default: 'attachment'
      },
      action: {
        type: String,
        default: getUploadUrl()
      },
      beforeUpload: Function,
      autoFetch: {
        type: Boolean,
        default: true
      },
      type: String,
      extraData: {
        type: Object,
        default: () => ({})
      }
    },
    data() {
      return {
        fileList: this.value || [],
        innerUnId: this.unid || '',
        showDialog: false
      }
    },
    computed: {
      inputDisabled() {
        return this.disabled || (this.elForm || {}).disabled
      },
      headers() {
        return getHeader()
      }
    },
    watch: {
      unid: {
        immediate: true,
        async handler(newVal) {
          this.innerUnId = newVal
        }
      },
      value(newVal) {
        this.fileList = newVal
      },
      innerUnId: {
        immediate: true,
        async handler() {
          await this.fetchAttachments()
        }
      },
      fileList(newVal) {
        this.$emit('files-change', newVal)
      }
    },
    methods: {
      getFileIcon,
      getFileList() {
        return this.fileList
      },
      submit() {
        this.$refs.upload.submit()
      },
      handleClick(file) {
        this.curFile = file
        this.$refs.upload.$refs['upload-inner'].handleClick()
      },
      async uploadFile(obj) {
        try {
          const res = await uploadFile(obj.action, obj.file, {
            headers: obj.headers,
            onprogress: this.onUploadProgress,
            data: obj.data
          })
          if (res.code === 0) {
            this.$emit('on-success', res)
            if (this.curFile) {
              const index = this.fileList.findIndex(value => value.id === this.curFile.id)
              if (index > -1) {
                await this.deleteFile(this.curFile)
                this.fileList.splice(index, 1, res.data)
              }
            } else {
              this.fileList.push(res.data)
            }
          } else {
            this.$emit('on-error', res)
          }
        } catch (e) {
          console.error(e)
          this.$emit('on-error', e)
        }
        this.$emit('on-complete')
      },
      async beforeUploadFile(file) {
        if (this.accept !== '*/*') {
          if (!this.accept.split(',').includes(getFileSuffix(file.name, true))) {
            const message = `只允许上传${this.accept}格式的文件！`
            this.$message.warning(message)
            return Promise.reject(new Error(message))
          }
        }
        if (file.size / (1024 * 1024) > this.limitSize) {
          const message = `上传文件不能超过${this.limitSize}M！`
          this.$message.warning(message)
          return Promise.reject(new Error(message))
        }
        this.beforeUpload && (await this.beforeUpload())
        this.$emit('before-upload-file', file)
      },
      async deleteFile(row) {
        const res = await remove(row.id)
        return res.code === 0
      },
      async removeFile(row) {
        const success = await this.deleteFile(row)
        if (success) {
          this.fileList = this.fileList.filter(value => value !== row)
        }
      },
      async fetchAttachments() {
        if (this.autoFetch && this.innerUnId && this.innerUnId !== '') {
          const { data } = (await findAllByParentUnid(this.innerUnId)) || {}
          this.fileList = data || []
        }
      }
    }
  }
</script>

<style lang="scss">
  .upload-button-wrapper {
    + .el-button {
      margin-left: 10px;
    }

    .icon-attachment {
      color: var(--color-primary);
      font-weight: bold;
      font-size: 1.2em;
    }
  }

  .upload-button-file-list {
    height: 300px;
    padding: 10px;
    overflow: auto;

    .file-uploader-file-item {
      display: flex;
      align-items: center;
      height: 36px;
      margin-bottom: 6px;
      padding-right: 10px;
      padding-left: 10px;
      color: #808080;
      border: 1px solid #ccc;

      &:last-child {
        margin-bottom: 0;
      }

      .handle-buttons {
        .el-button--primary {
          color: var(--color-primary);
        }

        .el-button--danger {
          margin-left: 10px;
          color: #f56c6c;
        }
      }
    }

    .file-icon {
      display: inline-block;
      width: 24px;
      min-width: 24px;
      height: 24px;
      margin-right: 6px;
      background-repeat: no-repeat;
    }

    .file-list-empty {
      display: flex;
      align-items: center;
      justify-content: center;
      height: 100%;
      color: #808080;
    }
  }
</style>
